/*
 * @Vuthor: 黄达全
 * @Date: 2024-08-16 20:20:17
 * @LastEditTime: 2024-08-29 14:11:41
 */
import { reactive, ref, onMounted } from 'vue'
import type { Ref, ComputedRef } from 'vue'
import type { FormRules } from 'element-plus'
import type { ApiResponse } from "@/common/type"
import useElementPlus from "@/hooks/useElementPlus"


// 用于返回的表格相关功能的接口
export interface UseTableOptions<T extends Record<string, any>, V extends object> {
    addItem: (form: V) => Promise<ApiResponse<null>>
    deleteItem: (ids: number[]) => Promise<ApiResponse<null>>,
    updateItem: (item: T) => Promise<ApiResponse<null>>,
    fetchData?: (page: number, pageSize: number) => Promise<ApiResponse<{ total: number; records: T[] }>>,
    filterMethod?: (options: any) => Promise<ApiResponse<{ total: number; records: T[] }>>
    // 表单校验规则
    formRules: FormRules<T>
    initForm: V,
    title: string,
    canRun?: ComputedRef<boolean>,
    filterData?: any
}


// T: 表格数据类型
// V:新增表单数据类型
export function useTable<T extends Record<string, any>, V extends object>(options: UseTableOptions<T, V>) {
    const { message, messageBox } = useElementPlus()
    const height = document.documentElement.clientHeight - 44.33 - 42 - 60.67 - 14

    const isAddMode = ref(true)
    const drawerRef = ref<any>()
    const initForm = reactive<V>(options.initForm)
    const page = ref(1)
    const pageSize = ref(10)
    const total = ref(0)
    const tableData = ref<T[]>([]) as Ref<T[]>
    const deleteIds = ref<number[]>([])
    const filterData = options.filterData

    // 获取表格数据
    const getData = async () => {
        if (options.canRun && !options.canRun!.value) return;
        if (!options.fetchData) return
        const { data } = await options.fetchData(page.value, pageSize.value)
        total.value = data.total
        tableData.value = data.records as T[]
    }
    if (options.fetchData) {
        getData()
    }

    // 分页获取数据
    const getDataByPage = (e: number) => {
        page.value = e
        getData()
    }

    // 新增表格数据
    const add = async (cb: Function | null) => {
        const { code } = await options.addItem(initForm as V)
        if (code == 1) {
            message({
                message: `新增${options.title}成功`,
                type: "success"
            })
            if(options.filterMethod ) {
                filterTableData()
            }else{
                getData()
            }
            cb && cb()
            drawerRef.value.close()
        } else {
            message({
                message: `新增${options.title}失败`,
                type: "error"
            })
        }
    }

    // 删除表格数据
    // 1、勾选被删除元素
    const handleSelectionChange = (rows: T[]) => {
        deleteIds.value = rows.map((item: any) => item.id)
    }
    // 2、删除被勾选元素
    const del = async (id?: number, cb?: Function | null) => {
        messageBox('提示', `你正在删除此${options.title}，是否继续?`).then(async () => {
            const ids = typeof id === "number" ? [id] : Array.from(deleteIds.value)
            const { code } = await options.deleteItem(ids)
            if (code == 1) {
                message({
                    message: `删除${options.title}成功`,
                    type: "success"
                })
                if(options.filterMethod ) {
                    filterTableData()
                }else{
                    getData()
                }
                cb && cb()
            }
        }).catch((err) => {
            console.log(err)
            message({
                message: `取消删除${options.title}`,
                type: "info"
            })
        })
    }

    // 修改表格数据
    const editId = ref<number>()
    const update = async (cb: Function | null) => {
        const { code } = await options.updateItem({ id: editId.value!, ...initForm } as any)
        if (code == 1) {
            message({
                message: `编辑${options.title}成功`,
                type: "success"
            })
            if(options.filterMethod ) {
                filterTableData()
            }else{
                getData()
            }
            cb && await cb()
            drawerRef.value.close()
        } else {
            message({
                message: `编辑${options.title}失败`,
                type: "error"
            })
        }
    }

    // 判断是否是新增或修改
    const submitHandle = (cb: Function | null) => {
        isAddMode.value ? add(cb) : update(cb)
    }


    // 过滤操作
    const filterTableData = async () => {
        if (!options.filterMethod) return;
        const { data } = await options.filterMethod(filterData)
        total.value = data.total
        tableData.value = data.records as T[]
    }

    // 表格高度
    const tableRef = ref<HTMLDivElement>()
    const tableHeight = ref<number>(0)
    onMounted(() => {

        if (!tableRef.value) return
        tableHeight.value = tableRef.value!.clientHeight
    })

    return {
        // 查询数据
        page,
        pageSize,
        total,
        getData,
        tableData,
        getDataByPage,
        // 删除数据
        handleSelectionChange,
        deleteIds,
        del,
        // 修改数据
        editId,
        update,
        // 新增数据
        add,
        isAddMode,
        submitHandle,
        // 表单
        initForm,
        formRules: options.formRules,
        // 弹窗
        drawerRef,
        // 表格
        height,
        tableRef,
        tableHeight,
        filterTableData
    }
}
